import { ESGeoExtrudedPolygonUFMSFromCircle } from '.';
import { CzmESGeoExtrudedPolygonUFMS } from '../ESGeoExtrudedPolygonUFMS/CzmESGeoExtrudedPolygonUFMS';
import { createNextAnimateFrameEvent, reactArrayWithUndefined } from "earthsdk3";
import * as Cesium from 'cesium';
import { CzmESGeoExtrudedPolygon, ESCesiumViewer } from 'earthsdk3-cesium';
import { bindCustomEditing, ESJEditingBindModeType, ESJEditingMode } from "earthsdk3"

export class CzmESGeoExtrudedPolygonUFMSFromCircle<T extends ESGeoExtrudedPolygonUFMSFromCircle = ESGeoExtrudedPolygonUFMSFromCircle> extends CzmESGeoExtrudedPolygonUFMS<T> {
    static override readonly type = this.register<ESGeoExtrudedPolygonUFMSFromCircle, ESCesiumViewer>("ESCesiumViewer", ESGeoExtrudedPolygonUFMSFromCircle.type, this);

    // private _sEditing = this.disposeVar(new PositionEditing([this.sceneObject, 'position'], [this.sceneObject, 'positionEditing'], this.czmViewer));
    // get sEditing() { return this._sEditing; }

    constructor(sceneObject: T, czmViewer: ESCesiumViewer) {
        super(sceneObject, czmViewer);
        const viewer = czmViewer.viewer;
        if (!viewer) {
            console.warn(`viewer is undefined!`);
            return;
        }

        // {
        //     const update = () => {
        //         if (!this.sceneObject.positionEditing) return;
        //         const editingModes: string[] = [];
        //         if (this.editingBindMode == 'singlePoint') {
        //             if (!this.sceneObject.points || this.sceneObject.points.length <= 0) {
        //                 editingModes.push(ESJEditingMode.Place);
        //             }
        //             editingModes.push(ESJEditingMode.Translation);
        //         }
        //         this.czmViewer.startEditing(this.sceneObject, editingModes);

        //     }
        //     this.ad(bindCustomEditing(this.czmViewer, this.sceneObject, update.bind(this), 'positionEditing'));
        // }
        {
            const update = () => {
                sceneObject.points = sceneObject.position && this._getCircularCoordinates(sceneObject.position);
            }
            update();
            const event = this.ad(createNextAnimateFrameEvent(
                sceneObject.radiusChanged,
                sceneObject.sidesChanged,
                sceneObject.positionChanged,
                sceneObject.rotationChanged
            ))
            this.ad(event.don(update));
        }
        {
            this.ad(sceneObject.pointsChanged.don(() => {
                if (!sceneObject.points || sceneObject.points.length == 0) {
                    sceneObject.position = undefined;
                }
            }))
        }
        {
            const update = () => {
                sceneObject.show = !(!sceneObject.points || sceneObject.points.length == 0);
            }
            update()
            this.ad(sceneObject.positionEditingChanged.don(update))
        }
    }
    private _getCircularCoordinates(point: [number, number, number]) {
        // 都是在笛卡尔坐标下进行计算的
        const { sceneObject } = this;
        const radius = sceneObject.radius ?? ESGeoExtrudedPolygonUFMSFromCircle.defaults.radius;
        const sides = sceneObject.sides ?? ESGeoExtrudedPolygonUFMSFromCircle.defaults.sides;
        const circlePoints = [] as [number, number, number][];
        if (radius <= 0 || sides <= 0) return sceneObject.points
        let Cartesian3_to_WGS84 = function (point: Cesium.Cartesian3): [number, number, number] {
            let cartesian33 = new Cesium.Cartesian3(point.x, point.y, point.z);
            let cartographic = Cesium.Cartographic.fromCartesian(cartesian33);
            let lat = Cesium.Math.toDegrees(cartographic.latitude);
            let lng = Cesium.Math.toDegrees(cartographic.longitude);
            let alt = cartographic.height;
            return [lng, lat, alt];
        }
        //法向量
        const normalVector = Cesium.Cartesian3.fromDegrees(...point);
        // 辅助向量
        const auxiliaryVectorZ = new Cesium.Cartesian3(0, 0, 1);
        const auxiliaryVectorX = new Cesium.Cartesian3(1, 0, 0);
        // 向量点乘结果为正负1就是平行
        const circleStartPoint = Cesium.Cartesian3.cross(
            normalVector,
            Math.abs(Cesium.Cartesian3.dot(normalVector, auxiliaryVectorZ)) != 1 ? auxiliaryVectorZ : auxiliaryVectorX,
            new Cesium.Cartesian3()
        );
        // 归一化，乘半径
        Cesium.Cartesian3.normalize(circleStartPoint, circleStartPoint);
        Cesium.Cartesian3.multiplyByScalar(circleStartPoint, radius, circleStartPoint);
        // 通过旋转，计算圆点结果
        for (let j = 0; j <= sides; j++) {
            //获取旋转矩阵
            let quat = Cesium.Quaternion.fromAxisAngle(normalVector, j * 2 * Math.PI / sides + Cesium.Math.toRadians(135 - sceneObject.rotation[0]));
            let rot_mat3 = Cesium.Matrix3.fromQuaternion(quat);
            let m = Cesium.Matrix4.fromRotationTranslation(rot_mat3, Cesium.Cartesian3.ZERO);
            Cesium.Matrix4.multiplyByTranslation(m, circleStartPoint, m);
            const startPoint = Cesium.Matrix4.getTranslation(m, new Cesium.Cartesian3());
            Cesium.Cartesian3.add(Cesium.Cartesian3.fromDegrees(...point), startPoint, startPoint);
            circlePoints.push(
                Cartesian3_to_WGS84(startPoint),
            )
        }
        return circlePoints;
    }
}